package wiki.zimo.utils;

import wiki.zimo.annotation.Column;
import wiki.zimo.annotation.ID;
import wiki.zimo.annotation.Keyword;
import wiki.zimo.annotation.Table;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.List;

/**
 * @version v1.0
 * @auther: 子墨
 * @datetime: 2018/11/7 9:44
 * @description: 拼接SQL语句的工具类
 * 这里写为抽象类的原因是只有子类才能获取到泛型的实际类型
 * 如果直接new SQLUtils对象的话会抛出空指针异常
 * 应避免出现，所以不允许直接new SQLUtils对象
 */
public abstract class SQLUtils<T> {

    private Class<?> tType;// T的实例类型
    private Field[] fields;// T的所有成员变量
    private Table table;// 表名的注解对象
    private String tableName;// 表名

    //	private ID id;// 表的主键注解对象
    private String tableId;// 表的主键字段名

    //	private List<Column> tableColomns = new ArrayList<>();// 表的普通字段注解对象集合
    private List<String> tableFields = new ArrayList<>();// 表的普通字段名集合

    //	private List<Keyword> keyColomns = new ArrayList<>();// 表的模糊查询注解对象集合
    private List<String> keyWords = new ArrayList<>();// 表的模糊查询字段名集合


    /**
     * @auther: 子墨
     * @date: 2018/11/7 10:42
     * @describe: 获取注解，拿到表的字段
     * @param: []
     * @return:
     * @version v1.0
     */
    public SQLUtils() {
        // 获取范型T的实际类型
        tType = (Class) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
//		System.out.println("范型T的实际类型 -> " + tType);

        // 获取表的注解和表名
        table = tType.getAnnotation(Table.class);
        tableName = table.value();
//		System.out.println(tType + "的表名为 -> " + tableName);

        // 获取T的fields -> 成员变量
        fields = tType.getDeclaredFields();
        // 遍历成员变量获取注解
        for (int i = 0; i < fields.length; i++) {
            // 获取主键注解和主键字段名
            ID tempId = fields[i].getAnnotation(ID.class);
            if (tempId != null) {
//				id = tempId;
                tableId = tempId.value();
//				System.out.println(tType + "的主键名为 -> " + tableId);
            }
            // 获取普通列注解和普通列字段名
            Column column = fields[i].getAnnotation(Column.class);
            if (column != null) {
//				tableColomns.add(column);
                tableFields.add(column.value());
//				System.out.println(tType + "的普通列名为 -> " + column.value());
                // 获取模糊查询列注解和模糊查询列名
                Keyword keyword = fields[i].getAnnotation(Keyword.class);
                if (keyword != null) {
//					keyColomns.add(keyword);
                    keyWords.add(column.value());
//				    System.out.println(tType + "的模糊查询列名为 -> " + column.value());
                }
            }

        }
    }

    /**
     * @auther: 子墨
     * @date: 2018/11/7 10:52
     * @describe: 获取插入SQL语句
     * @param: []
     * @return: java.lang.String
     * @version v1.0
     */
    public String getInsertSql() {
        String sql = "insert into " + tableName + " values(";
        StringBuffer buffer = new StringBuffer(sql);
        for (int i = 0; i < tableFields.size() + 1; i++) {
            buffer.append("?");
            if (i < tableFields.size()) {
                buffer.append(",");
            }
        }
        buffer.append(")");
        sql = buffer.toString();
        System.out.println(sql);
        return sql;
    }

    /**
     * @auther: 子墨
     * @date: 2018/11/7 11:09
     * @describe: 获取删除SQL语句
     * @param: []
     * @return: java.lang.String
     * @version v1.0
     */
    public String getDeleteSql() {
        String sql = "delete from ";
        StringBuffer buffer = new StringBuffer(sql);
        buffer.append(tableName);
        buffer.append(" where ");
        buffer.append(tableId);
        buffer.append(" = ?");
        sql = buffer.toString();
        System.out.println(sql);
        return sql;
    }

    /**
     * @auther: 子墨
     * @date: 2018/11/7 11:08
     * @describe: 获取查找一条记录的SQL语句
     * @param: []
     * @return: java.lang.String
     * @version v1.0
     */
    public String getFindOneByIdSql() {
        String sql = "select * from ";
        StringBuffer buffer = new StringBuffer(sql);
        buffer.append(tableName);
        buffer.append(" where ");
        buffer.append(tableId);
        buffer.append(" = ? limit 1");
        sql = buffer.toString();
        System.out.println(sql);
        return sql;
    }

    /**
     * @auther: 子墨
     * @date: 2018/11/7 11:11
     * @describe: 获取查找所有记录的SQL语句
     * @param: []
     * @return: java.lang.String
     * @version v1.0
     */
    public String getFindAllSql() {
        String sql = "select * from ";
        StringBuffer buffer = new StringBuffer(sql);
        buffer.append(tableName);
        sql = buffer.toString();
        System.out.println(sql);
        return sql;
    }

    /**
     * @auther: 子墨
     * @date: 2018/11/7 11:00
     * @describe: 获取更新SQL语句
     * @param: []
     * @return: java.lang.String
     * @version v1.0
     */
    public String getUpdateSql() {
        String sql = "update ";
        StringBuffer buffer = new StringBuffer(sql);
        buffer.append(tableName);
        buffer.append(" set ");
        for (int i = 0; i < tableFields.size() + 1; i++) {
            if (i < tableFields.size()) {
                buffer.append(tableFields.get(i) + " = ?");
                if (i < tableFields.size() - 1) {
                    buffer.append(" , ");
                }
            }
        }
        buffer.append(" where ");
        buffer.append(tableId);
        buffer.append(" = ?");
        sql = buffer.toString();
        System.out.println(sql);
        return sql;
    }

    /**
     * @auther: 子墨
     * @date: 2018/11/8 18:44
     * @describe: 获取模糊查询SQL语句
     * @param: []
     * @return: java.lang.String
     * @version v1.0
     */
    public String getLikeSql() {
        if (keyWords.size() <= 0) {
            return null;
        }
        String sql = "select * from ";
//		String sql1 = "select * from where cid like '%%' or ";
        StringBuffer buffer = new StringBuffer(sql);
        buffer.append(tableName);
        buffer.append(" where ");
        for (int i = 0; i < keyWords.size() + 1; i++) {
            if (i < keyWords.size()) {
                buffer.append(keyWords.get(i) + " like ?");
                if (i < keyWords.size() - 1) {
                    buffer.append(" or ");
                }
            }
        }
        sql = buffer.toString();
        System.out.println(sql);
        return sql;
    }

    /**
     * @auther: 子墨
     * @date: 2018/11/11 19:12
     * @describe: 统计SQL语句中，出现的某个参数的个数
     * @param: [sql, param]
     * @return: int
     * @version v1.0
     */
    public int countSqlParams(String sql, String param) {
        int fromIndex = 0;
        int count = 0;
        while (true) {
            int index = sql.indexOf(param, fromIndex);
            if (-1 != index) {
                fromIndex = index + 1;
                count++;
            } else {
                break;
            }
        }
        return count;
    }
}
